/*!
 * 
 * 主工具。
 * 
 * @author ChenYong
 * @date 2015-10-23
 * 
 */



//--------------------[常量定义]--------------------/
/** 用户名正则表达式 */
var usernameRE = /^[0-9A-Za-z_]{5,20}$/i;
/** 邮箱正则表达式 */
var mailRE = /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/i;
/** 手机号正则表达式 */
var phoneRE = /^1[3-9][0-9]{9}$/i;
/** 密码正则表达式 */
var passwdRE = /^[0-9a-zA-Z]{6,20}$/i;
/** 验证码正则表达式 */
var captchaRE = /^[0-9A-Za-z]{6}$/i;
/** 完整 URL 正则表达式 */
var urlFullRE = /^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?#]\S*)?$/i;
/** 部分 URL 正则表达式 */
var urlOnlyRE = /^#\/[A-Za-z_.\d-]+(\/[A-Za-z_.\d-]+)*$/i;
/** 中文正则表达式 */
var chineseRE = /^[\u4e00-\u9fa50-9a-zA-Z_]+$/i;
/** 编码正则表达式 */
var codeRE = /^[A-Z]+[0-9A-Z]*$/i;
/** Font Awesome 字体正则表达式 */
var fontAwesomeRE = /^fa fa-[0-9a-z]+(-[0-9a-z]+)*$/i;
/** 数字正则表达式 */
var numberRE = /^[0-9]+$/i;
//--------------------[/常量定义]--------------------/



//--------------------[方法定义]--------------------/
/**
 * 
 * 对象为空。
 * 
 * @param o 对象
 * @returns {Boolean} 是否为空：
 * <ol>
 * 	<li>true-为空；</li>
 * 	<li>false-不为空。</li>
 * </ol>
 *  
 */
function isNull(o) {
	try {
		if (($.type(o) === "undefined") || (o == null)) {
			return true;
		}
		
		return false;
	} catch (e) {
		return true;
	}
}

/**
 * 
 * 对象不为空。
 * 
 * @param o 对象
 * @returns {Boolean} 是否为空：
 * <ol>
 * 	<li>true-不为空；</li>
 * 	<li>false-为空。</li>
 * </ol>
 * 
 */
function isNotNull(o) {
	return !isNull(o);
}

/**
 * 
 * 字符串为空。
 * 
 * @param str 字符串
 * @returns {Boolean} 是否为空：
 * <ol>
 * 	<li>true-为空；</li>
 * 	<li>false-不为空。</li>
 * </ol>
 *  
 */
function isEmpty(str) {
	try {
		if (($.type(str) === "undefined") || (str == null) || ($.type(str) !== "string") || ($.trim(str).length === 0)) {
			return true;
		}
		
		return false;
	} catch (e) {
		return true;
	}
}

/**
 * 
 * 字符串不为空。
 * 
 * @param str 字符串
 * @returns {Boolean} 是否为空：
 * <ol>
 * 	<li>true-不为空；</li>
 * 	<li>false-为空。</li>
 * </ol>
 * 
 */
function isNotEmpty(str) {
	return !isEmpty(str);
}

/**
 * 
 * 判断变量 v 是否存在。
 * 
 * @param v 变量
 * @returns {Boolean} 是否存在：
 * <ol>
 * 	<li>true-存在；</li>
 * 	<li>false-不存在。</li>
 * </ol>
 * 
 */
function isVarExists(v) {
	try {
		if ($.type(v) === "undefined") {
			return false;
		}
		
		return true;
	} catch (e) {
		return false;
	}
}

/**
 * 
 * 判断非空变量是否为原生对象。
 * 
 * @param o 变量
 * @returns {Boolean} 是否为原生对象：
 * <ol>
 * 	<li>true-是；</li>
 * 	<li>false-否。</li>
 * </ol>
 * 
 */
function isObject(o) {
	try {
		return $.isPlainObject(o);
	} catch (e) {
		return false;
	}
}

/**
 * 
 * 判断非空变量是否为 jQuery 对象。
 * 
 * @param o 变量
 * @returns {Boolean} 是否为 jQuery 对象：
 * <ol>
 * 	<li>true-是；</li>
 * 	<li>false-否。</li>
 * </ol>
 * 
 */
function is_jQueryObj(o) {
	try {
		return isNotNull(o) && isNotEmpty(o.jquery);
	} catch (e) {
		return false;
	}
}

/**
 * 
 * 判断变量是否为数字。
 * 
 * @param o 变量
 * @returns {Boolean} 是否为数字：
 * <ol>
 * 	<li>true-是；</li>
 * 	<li>false-否。</li>
 * </ol>
 * 
 */
function isNumber(o) {
	try {
		return $.isNumeric(o);
	} catch (e) {
		return false;
	}
}

/**
 * 
 * 判断变量是否为数组。
 * 
 * @param o 变量
 * @returns {Boolean} 是否为数组：
 * <ol>
 * 	<li>true-是；</li>
 * 	<li>false-否。</li>
 * </ol>
 * 
 */
function isArray(o) {
	try {
		return $.isArray(o);
	} catch (e) {
		return false;
	}
}

/**
 * 
 * 判断变量是否为函数。
 * 
 * @param o 变量
 * @returns {Boolean} 是否为函数：
 * <ol>
 * 	<li>true-是；</li>
 * 	<li>false-否。</li>
 * </ol>
 * 
 */
function isFunction(o) {
	try {
		return $.isFunction(o);
	} catch (e) {
		return false;
	}
}

/**
 * 
 * 检查邮箱格式是否正确。
 * 
 * @param mail 邮箱
 * @returns {Boolean} 格式是否正确：
 * <ol>
 * 	<li>true-正确；</li>
 * 	<li>false-错误。</li>
 * </ol>
 * 
 */
function checkMail(mail) {
	if (isNotEmpty(mail)) {
		if ((mail.length >= 5) && (mail.length <= 30)) {
			return mailRE.test(mail);
		}
	}
	
	return false;
}
/**
 * 验证手机号
 * @param phone
 */
function checkPhoneNumber(phone){
	if(isNotEmpty(phone)){
		return phoneRE.test(phone);
	}
}
/**
 * 验证密码
 * @param pwd
 * @returns {boolean}
 */
function checkPassword(pwd){
	if(isNotEmpty(pwd)){
		return passwdRE.test(pwd);
	}
}


/**
 * 
 * 替换所有旧字符串。
 * 
 * @param oldStr 旧字符串
 * @param newStr 新字符串
 * @returns 替换后的字符串
 * 
 */
String.prototype.replaceAll = function(oldStr, newStr) {
	return this.replace(new RegExp(oldStr, "gm"), newStr);
};

/**
 * 
 * 格式化字符串。<br>
 * 两种调用方式：<br>
 * var s1 = "我是{0}，今年{1}了";<br>
 * var s2 = "我是{name}，今年{age}了";<br>
 * var result1 = s1.format("loogn", 22);<br>
 * var result2 = s2.format({name : "loogn", age : 22});<br>
 * 结果：“我是loogn，今年22了”。<br>
 * 
 * @param param 参数
 * @returns {String} 格式化后的字符串
 * 
 */
String.prototype.format = function(param) {
	if (arguments.length > 0) {
		var result = this;
		
		if ((arguments.length === 1) && ($.type(param) === "object")) {
			for (var key in param) {
				var reg = new RegExp("({" + key + "})", "g");
				
				result = result.replace(reg, param[key]);
			}
		} else {
			for (var i = 0; i < arguments.length; i++) {
				if ($.type(arguments[i]) === "undefined") {
					return "";
				} else {
					var reg = new RegExp("({[" + i + "]})", "g");
					
					result = result.replace(reg, arguments[i]);
				}
			}
		}
		
		return result;
	} else {
		return this;
	}
};

/**
 * 
 * 判断父节点是否包含子节点。
 * 
 * @param parentNode 父节点
 * @param childNode 子节点
 * @returns
 * <ol>
 * 	<li>true-包含；</li>
 * 	<li>true-不包含。</li>
 * </ol>
 * 
 */
function containsNode(parentNode, childNode) {
	if (parentNode.contains) {
		return (parentNode != childNode) && parentNode.contains(childNode);
	} else {
		return !!(parentNode.compareDocumentPosition(childNode) & 16);
	}
}

/**
 * 
 * 检查悬停事件，用于解决绑定 mouseover 和 mouseout 事件时，重复执行的问题。<br>
 * <b style="color: red;">只支持 mouseover 和 mouseout 事件。</b>
 * 
 * @param e 事件
 * @param target 被检查的目标
 * @returns {Boolean} 
 * <ol>
 * <li>当事件是 mouseover 或 mouseout事件时，返回 true/false；</li>
 * <li>当事件是其他事件时，返回 false。</li>
 * </ol>
 * 
 */
function checkHover(e, target) {
	if (isNull(e) || isNull(target)) {
		return false;
	}
	
	if (e.type == "mouseover") {
		return !containsNode(target, e.relatedTarget || e.fromElement)
				&& !((e.relatedTarget || e.fromElement) === target);
	} else if (e.type == "mouseout") {
		return !containsNode(target, e.relatedTarget || e.toElement)
				&& !((e.relatedTarget || e.toElement) === target);
	} else {
		return false;
	}
}

/**
 *
 * 时间对象的格式化。
 *
 */
Date.prototype.format = function(format) {
	/*
	 * eg:format="yyyy-MM-dd hh:mm:ss";
	 */
	var o = {
		"M+" : this.getMonth() + 1, // month
		"d+" : this.getDate(), // day
		"h+" : this.getHours(), // hour
		"m+" : this.getMinutes(), // minute
		"s+" : this.getSeconds(), // second
		"q+" : Math.floor((this.getMonth() + 3) / 3), // quarter
		"S" : this.getMilliseconds() // millisecond
	}

	if (/(y+)/.test(format)) {
		format = format.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
	}

	for (var k in o) {
		if (new RegExp("(" + k + ")").test(format)) {
			format = format.replace(RegExp.$1, RegExp.$1.length == 1 ? o[k] : ("00" + o[k]).substr(("" + o[k]).length));
		}
	}

	return format;
}
//--------------------[/方法定义]--------------------//